import Cocoa


extension Int {
    var customProperty :String {
        return "This is \(self)"
    }
    func multiplyBy(_ num:Int) -> Int {
        return num * self
    }
}
print(7.customProperty)
print(14.multiplyBy(3))


/// catch the value
///
/// - Parameter amount: forIncrement
/// - Returns: a value
func makeIncrementer(forIncrement amount:Int)->() ->Int {
    var runnongToal = 0
    func incrementer() -> Int {
        runnongToal +=  amount
        return runnongToal
    }
    return incrementer
}
let names = ["Chris","Alex","Ewa","Barry","Daniella"]

func backWard(_ s1:String,_ s2:String) ->Bool {
    return s1  > s2
}
var reverserdNames = names.sorted(by: backWard)
//Closures
reverserdNames = names.sorted(by: { (s1:String, s2:String) -> Bool in
    return s1 > s2
})
reverserdNames = names.sorted(by: { (s1, s2) -> Bool in
    s1 > s2
})
reverserdNames = names.sorted(by: {$0 > $1})
reverserdNames = names.sorted(by: >)
//Trailing Closures
func someFunctionThatTakesAClosure(closure:()->Void) {
    //    function body
}

// this is do not use the Trailing Closures
someFunctionThatTakesAClosure(closure:{
    //Closure body
})
//use trailing Closures call
someFunctionThatTakesAClosure {
    // Closure body
}
reverserdNames = names.sorted() {$0 > $1}
reverserdNames = names.sorted {$0 > $1}
let digitName = [0:"Zero",1:"One",2:"Two",3:"Tree",4:"Four",5:"Five",
                 6:"Six",7:"Seven",8:"Eight",9:"Nine",]
let numbers = [16,58,510]

//var useful things that can chnage the status
let strings = numbers.map { (number) -> String in
    var number = number
    var output = ""
    repeat {
        output = digitName[number % 10]! + output
        number /= 10
    } while number > 0
    return output
}

//func type as the return type
func setpForward(_ input:Int) -> Int {
    return input + 1
}
func setBackward(_ input:Int) -> Int {
    return input - 1
}
//
func chooseStepFunction(backward:Bool) ->(Int) -> Int {
    return backward ?setpForward : setBackward
}
var currentValuee = 3
//use the key func of the bool
let moveNearerToZero = chooseStepFunction(backward: currentValuee > 0)
// Multiple return value function
func minMax(array:[Int]) -> (min:Int,max:Int){
    var currentMin = array[0]
    var currentMax = array[1]
    for value in array[1..<array.count] {
        if  value < currentMin {
            currentMin = value
        } else if  value > currentMax {
            currentMax = value
        }
    }
    return (currentMin,currentMax)
}
func someFunction(firstParameterName:Int,secondParameterName:Int) {
    
}
someFunction(firstParameterName: 1, secondParameterName: 2)
//Specified parameter label(指定参数标签)
func someFunction(argumentLabel parameterName:Int) {
    //在函数体内,parameterName 代表参数值
}
func greet(person:String,from hometown:String) -> String {
    return "Hello\(person)! Glad you could visit from \(hometown)."
}
print(greet(person: "Bill", from: "Cupertino"))

func arithmeticMean(_ numbers:Double...) -> Double {
    var total:Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1,2,3,4,5)
arithmeticMean(3,8.25,18.75)
struct FixedLengthRange {
    var firstValue:Int
    let length:Int
}
var rangeOrThreeItems = FixedLengthRange(firstValue: 0, length: 3)
rangeOrThreeItems.firstValue = 6

class DataImporter {
    var fileName = "data.txt"
}

class DataManager {
    lazy var importer = DataImporter()
    var data = [String]()
}
let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")
//computed properties

struct Point {
    var x = 0.0, y = 0.0
}
struct Size {
    var width = 0.0 , height = 0.0
}
struct Rect {
    var origin = Point()
    var size = Size()
    var center:Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set(newCenter) {
            origin.x = newCenter.x - (size.width / 2)
            origin.y = newCenter.y - (size.height / 2)
        }
    }
}

var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0))
let initialSquareCenter = square.center
square.center = Point(x: 15.0, y: 15.0)
//print("square.origin is now at(\(square.origin.x),\(square.origin.y)")

struct AlternattiveRect {
    var origin = Point()
    var size = Size()
    var center:Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set {
            origin.x = newValue.x - (size.width / 2)
            origin.y = newValue.y - (size.height / 2)
        }
    }
}
struct Cuboid {
    var width = 0.0 , height = 0.0, depth = 0.0
    var volume:Double {
        return width * height * depth
    }
}
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
//打印 "the volume of fourByFiveByTwo is 40.0"
struct SomeStructure {
    static var storedTypeProperty = "Some value"
    static var computedTypeProperty:Int {
        return 1
    }
}

enum SomeEnumeration {
    static var storedTypeProperty = "Some value"
    static var computerTypeProperty:Int {
        return 6
    }
}
class SomeClass {
    static var storedTypeProperty = "Some value"
    static var computerTypeProperty:Int {
        return 27
    }
    class var overriderableComputedTypeProperty:Int {
        return 107
    }
}

print(SomeStructure.storedTypeProperty)
SomeStructure.storedTypeProperty  = "Another value"
print(SomeStructure.storedTypeProperty)
print(SomeEnumeration.computerTypeProperty)
print(SomeClass.computerTypeProperty)

struct AudioChannel {
    static let thresholdLevel = 10
    static var maxInputLevelForAllChannels = 0
    var currentLevel:Int = 0 {
        didSet {
            if currentLevel > AudioChannel.thresholdLevel {
                currentLevel = AudioChannel.thresholdLevel
            }
            if currentLevel>AudioChannel.maxInputLevelForAllChannels
            {
                AudioChannel.maxInputLevelForAllChannels = currentLevel
            }
        }
    }
}
var leftChannel = AudioChannel()
var rightChannel = AudioChannel()
struct TimeTable {
    let multiplier:Int
    subscript(index:Int) -> Int {
        return multiplier * index
    }
}

let threeTimeTable = TimeTable(multiplier: 3)

struct Matrix {
    let rows:Int, columns:Int
    var grid:[Double]
    init(rows: Int, columns: Int) {
        self.rows = rows
        self.columns = columns
        grid = Array(repeating: 0.0, count: rows * columns)
    }
    func indexIsValid(row:Int,column:Int) -> Bool {
        return row >= 0 && row < rows && column >= 0 && column < columns
    }
    subscript(row:Int,column:Int) -> Double {
        get {
            assert(indexIsValid(row: row, column: column),"Index out of range")
            return grid[(row * column) + column]
        }
        set {
            assert(indexIsValid(row: row, column: column),"Index out of range")
           grid[(row * column) + column] = newValue
        }
    }
    func indexIsValid(row:Int,colum:Int) -> Bool {
        return row >= 0 && row < rows && colum >= 0 && colum < columns
    }
}

var matrix = Matrix(rows: 2, columns: 2)
//matrix[0,1] = 1.5
//matrix[1,0] = 3.2
//let someValue = matrix[2,2]class
class Food {
    var name:String
    init(name:String) {
        self.name = name
    }
    convenience init() {
        self.init(name: "[Unnamed]")
    }
}
let namedMeat = Food(name: "Bacon")
let mysteryMeat = Food()
class RecipeIngredient:Food {
    var quantity:Int
   init(name: String,quantity:Int) {
        self.quantity = quantity
        super.init(name: name)
    }
     override convenience init(name: String) {
       self.init(name: name, quantity: 1)
    }
}

let wholeNumber:Double = 12345.0
let pi = 3.1415926
if Int(exactly: wholeNumber) != nil {
    print("\(wholeNumber) conversion to Int maintains value")
}
//打印“12345.0 conversion to int maintains value"
let valueChanged = Int(exactly: pi)
//valueChanged 是Int? 类型, 不是Int 类型
if valueChanged == nil {
    print("\(pi) conversion to Int does not maintain value")
}
//打印 ”3.14159 convversion to Int does not maintain value“
//下列中, 定义一个名为Animal 的结构体 允许构造失败
struct Animal {
    let species:String
    init?(species:String) {
        if species.isEmpty {
            return nil
        }
        self.species = species
    }
}

let someCreature = Animal(species: "Giraffe")
if let giraffe = someCreature {
    print("An animal was initialized with a species of\(giraffe.species)")
}

struct Checkerboard {
    let boardColors:[Bool] = {
        var temporaryBoard = [Bool]()
        var isBlack = false
        for i in 1...8 {
            for j in 1...8 {
                temporaryBoard.append(isBlack)
                isBlack = !isBlack
            }
            isBlack = !isBlack
        }
        return temporaryBoard
    }()
    func squareIsBlackAtRow(row:Int,column:Int) -> Bool {
        return boardColors[(row * 8) + column]
    }
}

let board = Checkerboard()
print(board.squareIsBlackAtRow(row: 0, column: 1))
print(board.squareIsBlackAtRow(row: 7, column: 7))

class Customer {
    let name:String
    var card:CreditCard?
    init(name:String) {
        self.name = name
    }
    deinit {
        print("\(name) is being deinitialized")
    }
}

class CreditCard {
    let number:UInt64
    unowned let customer:Customer
    init(number:UInt64,customer:Customer) {
        self.number = number
        self.customer = customer
    }
    deinit {
        print("带你走向荣华富贵")
    }
}

//泛型函数
func swapTwoValue<T>(_ a:inout T, _ b: inout T) {
    let temporaryA = a
        a = b
        b = temporaryA
}
var someInt = 3
var anotherInt = 107
swap(&someInt, &anotherInt)
print(someInt,anotherInt)
var someString = "hello"
var anotherString = "world"
swap(&someString, &anotherString)
print(someString,anotherString)

struct Instack<Element>{
    var items = [Element]()
    mutating func push(_ item:Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
}

var statckOfString = Instack<String>()
statckOfString.push("uno")
statckOfString.push("dos")
statckOfString.push("tres")
statckOfString.push("cuatro")
//let fileManager = FileManager.default
//let URL = NSURL.fileURL(withPath: "/path/to/file")
//do {
//    try fileManager.removeItem(at: URL)
//} catch let error as NSError {
//    print("Error:\(error.domain)")
//}

class SerializedDocument:NSDocument {
    static let ErrorDomain = "com.example.error.serialized-document"
    var representeObject:[String:AnyObject] = [:]
    override func read(from fileWrapper: FileWrapper, ofType typeName: String) throws {
        guard let data = fileWrapper.regularFileContents else {
            throw NSError(domain: NSURLErrorDomain, code: NSURLErrorCannotOpenFile, userInfo: nil)
        }
        if case let JSON as [String:AnyObject] = try JSONSerialization.jsonObject(with:data, options: []) {
            self.representeObject = JSON
        } else {
            throw NSError(domain:SerializedDocument.ErrorDomain , code: -1, userInfo: nil)
        }
    }
}
// get file Path
let fileManager = FileManager.default
let urlForDocument = fileManager.urls(for: .documentDirectory, in: .userDomainMask)
let url = urlForDocument[0] as URL
print(url)

//对指定路径执行浅搜索,返回指定目录路径下的文件、子目录及符号链接的列表
let contentsOfPath = try? fileManager.contentsOfDirectory(atPath: url.path)
let contentsOfURL = try?  fileManager.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
//深度遍历 , 会递归遍历子文件夹(但不会递归符号链接)
let enumeratorAtpath = fileManager.enumerator(at: url, includingPropertiesForKeys: nil, options: .skipsHiddenFiles, errorHandler: nil)
//深度遍历，会递归遍历子文件夹（包括符号链接，所以要求性能的话用enumeratorAtPath）
let subPaths = fileManager.subpaths(atPath: url.path)

//判断文件或文件夹是否存在
let filePath:String = NSHomeDirectory() + "/Doucments/hangge.txt"
let exist = fileManager.fileExists(atPath: filePath)
///创建文件夹
//let myDirectory:String = NSHomeDirectory() + "Documents/myFolder/Files"
//try! fileManager.createDirectory(atPath: myDirectory, withIntermediateDirectories: true, attributes: nil)

//func operateOnFile(description:Int32) {
//    let fileHandle = FileHandle(fileDescriptor: description)
//    defer {
//        fileHandle.closeFile()
//    }
//    let data = fileHandle.readDataToEndOfFile()
//    if /* onlyRead*/ {
//        fileHandle.closeFile()
//        return
//    }
//    let shouldWrite =
//    guard shouldWrite else {
//        return
//    }
//    fileHandle.seekToEndOfFile()
//    fileHandle.write()
//}

struct RegexHelper {
    let regex:NSRegularExpression
    init(_ pattern:String) throws {
        try regex = NSRegularExpression(pattern: pattern, options: .caseInsensitive)
    }
    func match(_ input:String) -> Bool {
        let matches = regex.matches(in: input, options: [], range: NSMakeRange(0, input.utf16.count))
        return matches.count > 0
    }
}
//var someArray = [1,2,3]
//let unOh = someArray.withUnsafeMutableBufferPointer({ (ptr)  in
//    return ptr
//})
//print(unOh[10])

var a = true
a.toggle()
print(a)
let fibs = [0,1,1,2,3,5]
var squared:[Int] = []
for fib in fibs {
    squared.append(fib * fib)
}
squared
let squares = fibs.map {fib in
    fib * fib
}
print(squared)

extension Array {
    public func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result {
        var result = initialResult
        for x in self {
            result = try nextPartialResult(result,x)
        }
        return result
    }
    }
enum Result<A> {
    case failure(Error)
    case success(A)
}
enum FileError:Error {
    case fileDoesNotExist
    case noPermission
}
//func contents(ofFile filename:String) -> Result<String>
//{
//    
//}
//
//let result = contents(ofFile: "Input.txt")
//switch result {
//case let .success(contents):
//    print(contents)
//case let .failure(error):
//    if let fileError = error as? FileError,
//    fileError == .fileDoesNotExist
//    {
//        print("File Not Found s")
//    }
//}

//class ViewController:NSViewController {
//    override func viewDidLoad() {
//        super.viewDidLoad()
//        Thread.detachNewThreadSelector(#selector(ViewController.downloadImage), toTarget: self, with: nil)
//
//        let myThread = Thread(target: self, selector: #selector(ViewController.downloadImage), object: nil)
//        myThread.start()
//    }
//    @objc func downloadImage() {
//        let imageUrl = "http://hangge.com/blog/images/logo.png"
//        let data = try! Data(contentsOf: URL(string: imageUrl)!)
//        print(data.count)
//    }
//}
class ViewController:NSViewController {
    var thread1:Thread?
    var thread2:Thread?
    let condition1 = NSCondition()
    let condition2 = NSCondition()
    override func viewDidLoad() {
        super.viewDidLoad()
        thread2 = Thread(target: self, selector: #selector(ViewController.method2), object: nil)
        
        thread1 = Thread(target: self, selector: #selector(ViewController.method1), object: nil)
        
        thread1?.start()
    }
  @objc  func method1(sender:Any) {
        for i in 0..<10 {
        print("Thread 1 running \(i)")
            sleep(1)
            if i == 2 {
                thread2?.start()
                condition1.lock()
                condition1.wait()
                condition1.unlock()
            }
        }
        print("Thread 1 over")
        condition2.signal()
        
    }
 @objc    func method2(sender:Any) {
        for i in 0..<10 {
            print("Thread 2 runing \(i)")
            sleep(1)
            if i == 2 {
                condition1.signal()
                condition2.lock()
                condition2.wait()
                condition2.unlock()
            }
        }
        print("Thread 2 over")
    }
    
}

let namesA = ["Palua","Elena","Zoe"]
var lastNameEndingInA:String?
for name in namesA.reversed() where name.hasSuffix("a") {
    lastNameEndingInA =  name
    break
}
lastNameEndingInA
extension Sequence {
    func last(where predicate:(Element) -> Bool) -> Element? {
        for element in reversed() where predicate(element) {
            return element
        }
        return nil
    }
}
let match = namesA.last{$0.hasSuffix("a")}
match
extension Array {
    func accumulate<Result>(_ initlalResult:Result,_ nextPartResult:(Result,Element)->Result) ->[Result]
    {
        var running = initlalResult
        return map({ next in
            running = nextPartResult(running,next)
            return running
        })
    }
}

[1,2,3,4].accumulate(0, +)
[1,5,6,7].accumulate(0, +)

//let serialQueue = DispatchQueue(label: "com.allaboutswift.gcd.serial", attributes: [.serial], target: .global())
//
//serialQueue.sync {
//    print(" serialQueue ... ")
//}
//
//serialQueue.async {
//    print(" serialQueue ... ")
//}

//func test(value:String) -> Void {
//
//}
//
//func test(value2:String)-> Void
//{
//
//}


let ages = ["Tim":53,"Angela":54,"Craig":44,"Jony":47,"Chris":37,"Michael":34]
func flatten<S:Sequence,T>(source:S)->[T] where S.Element == T? {
    let fittered = source.lazy.first {$0 != nil}
    return fittered?.map{$0} as! [T]
}
//ages.keys.filter{ name  in ages[name]!<50}.sorted()
//ages.filter{ (_,age) in age < 50}.map { (name,_) in name}.sorted()
ages.filter { (_, age) in age < 50 }
    .map { (name, _) in name }
    .sorted()
var s:String!="Hello"
s?.isEmpty
if let s = s {print(s)}
s = nil
s ?? "Goodbye"

let url1 = URL(string: "https://example.com/checkout")!
var request = URLRequest(url: url1)
request.httpMethod = "POST"
request.networkServiceType = .responsiveData //Prioritize
URLSession.shared.dataTask(with: request) {
    (data,response,error) in
    //...
    print(response!)
}
let arrayOfInt:[Int] = [1,2,3]
let arrayOfUInt:[UInt] = [1,2,3]
//arrayOfInt.map(numericCast()) as [UInt]
/*
 闭包和内存
 在swift中，除了类之外，函数(包括闭包)
 也是引用类型
 闭包可以捕获变量。如果这些变量自身是引用类型的话，闭包将持有对它们的强引用。比如，有一个FileHandle类型的handle变量
 一旦回调结束，URL session 将会释放闭包，它所闭合的那些变量（在这个列子中就是handle） 的引用计数将会被减去。
 闭包对变量的强引用是有必要的，否则你就有可能在闭包中访问了已经释放的i变量。
 */
let handle = FileHandle(forReadingAtPath: "out.html")
let request1 = URLRequest(url: URL(string: "https://www.objc.io")!)
URLSession.shared.dataTask(with: request1) { (data, _, _) in
    guard let theData = data else {return}
    handle?.write(theData)
}.resume()
/*
 // Do this framework Like this
 public func mustMethod() { ... }
 func onlyUsedInFramework() { ... }
 private func onlyUsedInFile() { ... }

 */
class MediaItem {
    var name: String
    init(name: String) {
        self.name = name
    }
}
class Movie: MediaItem {
    var director: String
    init(name: String, director: String) {
        self.director = director
        super.init(name: name)
    }
}
class Song: MediaItem {
    var artist: String
    init(name: String, artist: String) {
        self.artist = artist
        super.init(name: name)
    }
}

let library = [
    Movie(name: "Casablance", director: "Michael Curtiz"),
    Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),
    Movie(name: "Citizen Kane", director: "Orson Welles"),
    Song(name: "The One And Only", artist: "Chesney Hawkes"),
    Song(name: "Never Gonna Give You Up", artist: "Rick Astley")
]
var movieCount = 0
var songCount = 0

for item in library {
    if item is Movie {
        movieCount += 1
    } else if item is Song {
        songCount += 1
    }
}
for items in library {
    if items is Movie {
        Movie.init(name: "Things", director: "Another")
    }
    
}
func isEven<T:BinaryInteger>(_ i:T) -> Bool {
    return i % 2 == 0
}
var munuitem:NSMenuItem!
//munuitem.image?.isTemplate = true
//var myClosure: () -> String
//无返回值的闭包
//myClosure:() -> Void = {
//    print("Hello world")
//}
var mySecondClosure:(Int,Int) -> Int = {
    (a:Int,b:Int) -> Int in
    return a * b
}
mySecondClosure = {a,b in
     a * b
}
mySecondClosure = {
    $0 * $1
}

//闭包作为参数
func myOperation(_ a :Int, _ b:Int,operation:(Int,Int) ->Int) -> Int {
    let res = operation(a,b)
    return res
}
//let multipyClosure:(Int,Int) -> Int = {
//    $0 * $1
//}
let multipyClosure = {
    (a:Int,b:Int) in
    a * b
}
myOperation(4, 2, operation: multipyClosure)
myOperation(4, 2) { (a, b) -> Int in
    return a * b
}
myOperation(4, 2,operation:{
    $0 * $1
})
myOperation(4, 2, operation: *)
myOperation(4, 2) {
    $0 * $1
}
// 自动闭包
//捕获
//闭包可以从上下文中捕获常量、变量、并在自己的作用域内使用。
var counter = 0
let incrementCounter = {
    counter += 1
}

/*
 由于闭包定义和变量counter在同一作用域中
 所以闭包可以捕获并访问counter
 对变量counter做的任何改变，对比宝来说都是透明可见的。
 */
//eg.:2
func countingClosure() -> () -> Int {
    var counter = 0
    let incrementCounter:() -> Int = {
        counter += 1
        return counter
    }
    return incrementCounter
}
let name = ["ZZZZZZZZZ","BBB","A","CCCCC","EEEEEEE"]
name.sorted()

let values = [5,6,4,3,0,2,7]
values.forEach {
    print("element is \($0)")
}

let vakues = [1.5,10,4.88,3.2,8]
let res = vakues.filter {
    return $0 > 5
}
print(res)


protocol PickableEnum {
    var displayName: String {get}
    var permanentID: String {get}
    static var allValues: [Self] {get}
    static func formPermanentID(id: String) -> Self?
}
//extension PickableEnum where Self:RawRepresentable, Self.RawValue == Int
//{
//    var displayName:String
//    {
//        return Localised("\(type(of: self)).\(self)")
//        
//    }
//    var permanentID: String
//    {
//        return String(self)
//    }
//}

var num = [2,7,10,9]
func twoSum(_ nums:[Int], _ target:Int) -> [Int] {
    var a:Int = 0
    for i in nums {
    nums.map {
      if  $0 + i == target
        {
          a = i
        }
        
        }
      
    }
    return [a]
}
twoSum(num, 9)

let defaultHeight = 200
let defaultColor = NSColor.blue

protocol HelperViewFactoryProtocol {
    func configure()
    func position()
    func display()
    var height:Int {get}
    var parentView:NSView {get set}
}

fileprivate class Square:HelperViewFactoryProtocol {
    var parentView: NSView
    let height:Int
    var view:NSView
    init(height:Int = defaultHeight,parentView:NSView) {
        self.height = height
        self.parentView = parentView
        view = NSView()
    }
    
    func configure() {
    let frame = CGRect(x: 0, y: 0, width: height, height: height)
        view.frame = frame
        view.layer?.backgroundColor = defaultColor.cgColor
    }
    
    func position() {
        view.centerXAnchor 
    }
    
    func display() {
        configure()
        position()
        parentView.addSubview(view, positioned:.below, relativeTo: parentView)
    }
}
fileprivate class Circle:Square {
    override func configure() {
        super.configure()
        view.layer?.cornerRadius = view.bounds.width / 2
        view.layer?.masksToBounds = true
    }
}

fileprivate class Rectangle:Square {
    override func configure() {
        let frame = CGRect(x: 0, y: 0, width: height + height/2, height: height)
        view.frame = frame
        view.layer?.backgroundColor = NSColor.blue.cgColor
    }
}

func loginTrue(_ predicate:@autoclosure() -> Bool){
    if predicate() {
        print("True")
    }
}
loginTrue(2 > 1)

let num1 = [1,2,3,4,5,6,7]
let sortNum = num1.sorted { (a, b) -> Bool in
    a > b
}
func sjzFunc(_ a:Int) -> () -> Int {
    var sjz = 0
    func addSjz() -> Int {
        sjz += a
        return sjz
    }
    addSjz()
    print("sjz的值为:\(sjz),a的值为\(a)")
    return addSjz
}

let sjzF = sjzFunc(100)
print("值为:\(sjzF())")
print("值为:\(sjzF())")
print("值为:\(sjzF())")
print("值为:\(sjzF())")

var eatFull:((String) -> Void) = { (String) in
    
}

var food:String?
func eat(food:String,by:@escaping (String) -> Void) -> Void {
    print("发兴吃了:\(food)")
    eatFull = by
}
func eatFinish() -> Void {
    eatFull(food!)
}
eat(food: "si") { (a) in
 print(a)
}

func Fibonacci(n: Int) -> Int {
    if (n <= 2) {
        return 1
    }
    else
    {
        return Fibonacci(n: n-1) + Fibonacci(n: n - 2)
    }
}
Fibonacci(n: 6)

//let hashTable = NSHashTable(options: .copyIn)
//    hashTable.add

let socketFD = Darwin.socket(DOMAIN, SOCK_STREAM, 0)
func converIPToUint32(a:Int,b:Int,c:Int,d:Int) -> in_addr {
    return Darwin.in_addr(s_addr: __uint32_t((a << 0)|(b << 8)|(c << 16)|(6 << 24)))
}
var sock4:sockaddr_in = sockaddr_in()
sock4.sin_len = __uint8_t(MemoryLayout.size(ofValue:sock4))
sock4.sin_addr = converIPToUint32(a: 127, b: 0, c: 0, d: 1)
sock4.sin_port = CFSwapInt16BigToHost(9090)
//IPV4
sock4.sin_family = sa_family_t(AF_INET)
let pointer: UnsafePointer<sockaddr> = withUnsafePointer(to: &sock4, {$0.withMemoryRebound(to: sockaddr.self, capacity: 1, {$0})})
var result = Darwin.connect(socketFD, pointer, socklen_t(MemoryLayout.size(ofValue:sock4)))
guard result != -1 else {
    fatalError("Error in connect() function code is\(errno)")
}

var data = "你好我是阿帕奇".data(using: .utf8) ?? Data()
let rawPointer = data.withUnsafeMutableBytes ({ UnsafeRawPointer($0)})
var resultWrite = Darwin.write(socketFD, rawPointer, data.count)
guard resultWrite != -1 else {
    fatalError("Error in connect() function code is\(errno)")
//
//protocol Product {}
//class ConcreteProductA: Product {}
//class ConcreteProductB: Product {}
//class Client {
//    func createProduct(type:Int) -> Product {
//        if type == 0 {
//            return ConcreteProductA()
//
//        } else {
//            return ConcreteProductB()
//        }
//    }
//}
//
//let c = Client()
//c.createProduct(type: 0)
////Simple Factory
//class Client {
//    let s = Factory()
//}
//class Factory {
//    func createProduct(type:Int) -> Product {
//        if type == 0 {
//            return ConcreteProductA()
//
//        } else {
//            return ConcreteProductB()
//        }
//    }
    
//Factory Method
protocol Product{}
class ConcreteProductA:Product {}
class ConcreteProductB:Product{}
class Client {
    let f = Factory()
}
class Factory {
    func createProduct() -> Product? {return nil}
    func createProduct(Type:Int) -> Product {
        if Type == 0 {
            return ConcreteFactoryA().createProduct()
        } else {
            return ConcreteFactoryB().createProduct()
        }
    }
}
class ConcreteFactoryA:Factory {
    override func createProduct() -> Product? {
        return ConcreteProductA()
    }
}
class ConcreteFactoryB:Factory {
    override func createProduct() -> Product? {
        return ConcreteProductB()
    }
}

let c = Client()
//c.f.createProduct(type:0)
// Builder
struct Builder {
    var partA:String
    var partB:String
}
struct Product {
    var partA:String
    var partB:String
    init(builder:Builder) {
        partA = builder.partA
        partB = builder.partB
    }
}
let b = Builder(partA: "A", partB: "B")
let p = Product(builder:b)
//Prototype
protocol Prototype {
    func clone() -> Prototype
}
struct Product:Prototype {
    var title:String
    func clone() -> Prototype {
        return Product(title:title)
    }
}
let p1 = Product(title:"p1")
let p2 = p1.clone()
(p2 as? Product)?.title //output: P1
//Singleton
class Singleton {
    static let sharedInstance = Singleton()
    private init()
}
let s = Singleton.sharedInstance
let s1 = Singleton()//error:initializer is inaccessible due to 'private' protection level

class Singleton {
    static var singleton:Singleton? = nil
    private init() {}
    static func sharedInstance() -> Singleton {
        if singleton == nil {
            singleton = Singleton()
        }
        return singleton!
    }
}

let s = Singleton.sharedInstance()
let s2 = Singleton()// ERROR: initializer is inaccessible due to 'private' protection level
//Adapter
protocol Target {
    var value:String{get}
}
struct Adapter:Target {
    let adaptee:Adaptee
    var value:String {
        return "\(adaptee.value)"
    }
    init(_ adaptee:Adaptee) {
        self.adaptee = adaptee
    }
    
}
struct Adaptee {
    var value:Int
}
Adapter(Adaptee(value: 1)).value
//Bridge
protocol Switch {
    func turnOn(_ on:Bool)
}
class Equipment {
    let obj:Switch
    func trunOn(_ on :Bool) {
        obj.turnOn(on)
    }
    init(_ obj:Switch) {
        self.obj = obj
    }
}

class TV : Switch {
    func turnOn(_ on:Bool) {
        if on {
            //打开电视
        } else {
            //关闭电视
        }
    }
}

//Composite模式
protocol Component {
    func someMethod()
}
class Leaf:Component {
    func someMethod() {
        //Leaf
    }
}
class Composite: Component {
    var components = [Component]()
    func someMethod() {
        //Composite
    }
}
let leaf = Leaf()
let composite = Composite()
composite.components += [leaf]

composite.someMethod()
leaf.someMethod()

////Decorator
//protocol Component {
//    var cost:Int {get}
//}
//protocol Decorator:Component {
//    var cost:Component {get}
//    init(_ component:Component)
//}
//struct Coffee:Component {
//    var cost:Int
//}
//struct Sugar:Decorator {
//    var cost:Int {
//        return component.cost + 1
//    }
//    var component:Component
//    init(_ component: Component) {
//        self.component = component
//    }
//}
//
//struct Milk:Decorator {
//    var cost:Int {
//        return component.cost + 2
//    }
//    var component:Component
//    init(_ component: Component) {
//        self.component = component
//    }
//}
//Milk(Sugar(Coffee(cost: 19))).cost

protocol Facade {
    func simpleMethod()
}
class LegacyCode {
    func someMethod1() {}
    func someMethod2() {}
}
extension LegacyCode:Facade {
    func simpleMethod() {
        someMethod1()
        someMethod2()
    }
}
//class Client {
//    let f:Facade = LegacyCode()
//}
//let c = Client()
//c.f.simpleMethod()
struct TargetObject {
    var title:String?
    func printTitle() {
        print(title ?? "")
    }
}
class Cache {
    var targetObjects = [String:TargetObject]()
    func lookup(key:String) -> TargetObject {
        if targetObjects.index(forKey: key) == nil {
            return TargetObject()
        }
        return targetObjects[key]!
    }
}
//Proxy代理模式
protocol Subject {
    mutating func operation()
}
struct SecretObject:Subject {
    func operation() {
        //
    }
}
struct PublicObject:Subject {
    private lazy var s = SecretObject()
    mutating func operation() {
        s.operation()
    }
}
//var p = PublicObject()
p.operation()

protocol ChainTouchable {
    var next:ChainTouchable? {get}
    func  touch()
}
class ViewA:ChainTouchable {
    var next: ChainTouchable? = ViewB()
    func touch() {
        next?.touch()
    }
}
class ViewB: ChainTouchable {
    var next: ChainTouchable? = ViewC()
    func touch() {
        next?.touch()
    }
}
class ViewC: ChainTouchable {
    var next: ChainTouchable? = nil
    func touch() {
        print("V")
    }
}
//Command 命令模式
protocol Commmand {
    var operation:()->Void {get}
    var backup:String {get}
    func undo()
}
struct ConcreteCommand:Commmand {
    var backup: String
    var operation: () -> Void
    func undo() {
        print("Hello")
    }
}
struct Invoker {
    var command:Commmand
    func  execute() {
        command.operation()
    }
    func undo() {
        command.undo()
    }
}
let printA = ConcreteCommand(backup: "DefaultA") {
    print("A")
}
let i1 = Invoker(command: printA)
    i1.execute()
let printB = ConcreteCommand(backup: "DefaultB") {
    print("B")
}

let i2 = Invoker(command: printB)
    i2.execute()
    i2.undo()
//Interpreter 解释器模式
protocol Expression {
    func evaluate(_ context:String) -> Int
}
struct MyAdditionExpression:Expression {
    func evaluate(_ context: String) -> Int {
        return context.components(separatedBy: "加")
            .flatMap{ Int($0)
        }.reduce(0, +)
    }
}

//let c = MyAdditionExpression()
c.evaluate("1加1") //OUTPUT:2
//Iterator 迭代器模式

protocol AbstractIterator {
    func hasNext() -> Bool
    func next() -> Int?
}
class ConcreteIterator:AbstractIterator {
    private var currentIndex = 0
    var elements = [Int]()
    
    func next() -> Int? {
        guard currentIndex < elements.count else {currentIndex = 0;return nil}
        defer {currentIndex +=1}
        return elements[currentIndex]
    }
    func hasNext() -> Bool {
        guard currentIndex < elements.count else {
            currentIndex = 0
            return false
            
        }
        return elements[currentIndex] != nil
    }
}
    
    protocol AbstractCollection {
        func makeIterator() -> AbstractIterator
    }
    class ConcreteCollection: AbstractIterator {
        let iterator = ConcreteIterator()
        func add(_ e: Int) {
            iterator.elements.append(e)
        }
        
        func makeIterator() -> AbstractIterator {
            return iterator
        }
    }
    let g = ConcreteCollection()
        g.add(1)
        g.add(2)
        g.add(3)
        let iterator = c.makeIterator()
    while iterator.hasNext() {
        print(iterator.next() as Any)
    }
}
func swap<T>(_ nums:inout[T],_ p:Int,_ q:Int) {
    (nums[p],nums[q]) = [nums[q],nums[p]]
}



